<!--
 * @Description: 基础弹窗
 * @Author: chenju
 * @Date: 2022-01-20 10:37:36
 * @LastEditors: qingyang
 * @LastEditTime: 2023-07-20 18:49:27
-->
<template>
  <el-dialog
    :class="customClass"
    v-model="visibleComputed"
    :show-close="!props.loading"
    :before-close="handleClose"
    :width="widthComputed"
    destroy-on-close
    append-to-body
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    align-center
    v-bind="$attrs"
  >
    <template #header>
      <slot name="header">
        <div class="c-dialog__header">
          <span class="el-dialog__title">{{ props.title }}</span>
          <template v-if="props.descText">
            <el-divider class="c-dialog__title-vertical" direction="vertical"></el-divider>
            <span class="c-dialog__desc-title">{{ props.descText }}</span>
          </template>
        </div>
      </slot>
    </template>
    <template #default>
      <slot name="contentHeader"></slot>
      <div class="c-dialog__body-wrapper" :style="noScrollBodyStyle" v-if="props.fixedHeight">
        <slot></slot>
      </div>
      <!-- 上下最小边距为2个40px; header高度64px; footer高度68px-->
      <el-scrollbar v-bind="scrollBodyStyle" ref="scrollbarRef" v-loading="loading" v-else>
        <div class="c-dialog__body-wrapper">
          <slot></slot>
        </div>
      </el-scrollbar>
    </template>
    <template #footer v-if="footer">
      <slot name="footer">
        <div class="g-flex-between-center">
          <slot name="footerLeft">
            <div class="c-dialog__footer-desc-wrapper">
              <CIcon
                class="c-dialog__footer-desc-icon"
                :type="props.footerDescIcon"
                v-if="props.footerDescIcon"
              ></CIcon>
              <span class="c-dialog__footer-desc-text">{{ props.footerDescText }}</span>
            </div>
          </slot>
          <div>
            <el-button
              size="default"
              @click="emit('cancel')"
              v-if="props.showCancelButton"
              :loading="props.loading"
              >{{ cancelText }}</el-button
            >
            <el-button
              size="default"
              type="primary"
              @click="emit('confirm')"
              :loading="props.loading"
              :disabled="props.btnDisabled"
              >{{ props.confirmText }}</el-button
            >
          </div>
        </div>
      </slot>
    </template>
  </el-dialog>
</template>
<script lang="ts">
export default {
  name: 'CDialog'
};
</script>
<script lang="ts" setup>
import { computed, ref, defineProps, defineExpose, defineEmits } from 'vue';
import type { ElScrollbar } from 'element-plus';
import { useMessage } from '@/hooks/useMessage';
import { dialogProps, sizeMap } from './dialog';

const props = defineProps(dialogProps);
const emit = defineEmits(['update:visible', 'cancel', 'confirm']);
const { createConfirm } = useMessage();
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>();
const visibleComputed = computed({
  get: () => {
    return props.visible;
  },
  set: val => {
    emit('update:visible', val);
  }
});

const customClass = computed(() => {
  let cls = 'c-dialog-wrapper';
  if (props.size === 'auto') {
    cls += ' c-dialog-size__auto';
  }
  return cls;
});

const scrollToBottom = () => {
  const wrap: any = scrollbarRef.value?.wrapRef;
  let max = wrap?.scrollHeight - wrap?.clientHeight;
  scrollbarRef.value?.setScrollTop(max);
};

const widthComputed = computed(() => {
  return sizeMap[props.size];
});

/**
 * body的最大高度
 */
const bodyMaxHeight = computed(() => {
  return props.footer
    ? `calc(100vh - 80px - 64px - 68px - ${props.contentHeader || 0}px)`
    : `calc(100vh - 80px - 64px - ${props.contentHeader || 0}px)`;
});

/**
 * scroll body的高度
 */
const scrollBodyStyle = computed(() => {
  if (props.fixedHeight) {
    return {
      height: bodyMaxHeight.value
    };
  } else {
    return {
      maxHeight: bodyMaxHeight.value
    };
  }
});

/**
 * no scroll body的高度
 */
const noScrollBodyStyle = computed(() => {
  return {
    height: bodyMaxHeight.value,
    padding: '0px'
  };
});

// 关闭前操作
const handleClose = (done: () => void) => {
  if (props.confirmBeforeClose) {
    createConfirm('提示', props.confirmBeforeCloseText, {
      iconType: 'warning'
    }).then(() => {
      done();
    });
  } else {
    done();
  }
};
defineExpose({
  scrollToBottom
});
</script>
<style lang="scss">
@import '../styles/index.scss';
</style>
